<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge" ><![endif]-->
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Create Custom Link</title>
  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<script type="text/javascript">
function add(type)
{
	try
	{
		var link = document.getElementById('link').value;
		var obj = JSON.parse(link.substring(link.indexOf(',') + 1));

		if (type == 'link')
		{
			obj.actions.push({open: document.getElementById('href').value});
		}
		else if (type == 'wait')
		{
			var wait = document.getElementById('wait').value;
			obj.actions.push({wait: (wait != '') ? wait : 1000});
		}
		else if (type == 'viewbox')
		{
			var tokens = document.getElementById('viewbox').value.split(' ');

			if (tokens.length > 3)
			{
				var action = {};
				action.viewbox = {x: parseInt(tokens[0]), y: parseInt(tokens[1]),
					width: parseInt(tokens[2]), height: parseInt(tokens[3])};

				if (tokens.length > 4)
				{
					action.border = parseInt(tokens[4]);
				}

				obj.actions.push(action);
			}
			else
			{
				showMessage('Missing arguments');
			}
		}
		else if (type == 'tags')
		{
			var hidden = document.getElementById('hiddenTags').value.split(' ');
			var visible = document.getElementById('visibleTags').value.split(' ');

			if (hidden.length > 0 || visible.length > 0)
			{
				var action = {};
				var add = false;

				if (hidden.length > 0)
				{
					if (hidden[0] == '*')
					{
						action.visible = [];
						add = true;
					}
					else if (hidden[0] != '')
					{
						action.hidden = hidden;
						add = true;
					}
				}

				if (visible.length > 0)
				{
					if (visible[0] == '*')
					{
						action.hidden = [];
						add = true;
					}
					else if (visible[0] != '')
					{
						action.visible = visible;
						add = true;
					}
				}

				if (add)
				{
					obj.actions.push({tags: action});
				}
				else
				{
					showMessage('Missing arguments');
				}
			}
		}
		else
		{
			var action = document.getElementById('parallel').checked && obj.actions.length > 0 ?
				obj.actions[obj.actions.length - 1] : {};
			var selector = {};
			var cells = document.getElementById('cells').value;
			var exclude = document.getElementById('exclude').value;
			var name = document.getElementById('action').value;

			if (cells.length > 0)
			{
				selector['cells'] = cells.split(' ');
			}

			if (exclude.length > 0)
			{
				selector['excludeCells'] = exclude.split(' ');
			}

			var tags = document.getElementById('tags').value;

			if (tags == '*')
			{
				selector['tags'] = [''];
			}
			else if (tags.length > 0)
			{
				selector['tags'] = tags.split(' ');
			}

			if (name == 'style' || name == 'toggleStyle')
			{
				var key = document.getElementById('key').value;
				selector.key = (key != '') ? key : 'flowAnimation';
			}

			if (name == 'style' || name == 'opacity')
			{
				var value = document.getElementById('value').value;
				selector.key = (value != '') ? value : '1';
			}

			if (name == 'fadeIn' || name == 'fadeOut')
			{
				selector.delay = 1000;
			}

			if (name == 'wipeIn' || name == 'wipeOut')
			{
				action.delay = 30;
				action.steps = 30;
			}

			action[name] = selector;

			if (!document.getElementById('parallel').checked)
			{
				obj.actions.push(action);
			}
		}

		document.getElementById('link').value = 'data:action/json,' + JSON.stringify(obj, null, 2);
	}
	catch (e)
	{
		showMessage(e);
	}
};

function clearInput()
{
	document.getElementById('action').value = 'toggle';
	document.getElementById('key').value = '';
	document.getElementById('value').value = '';
	document.getElementById('cells').value = '';
	document.getElementById('exclude').value = '';
	document.getElementById('tags').value = '';
	document.getElementById('href').value = '';
	document.getElementById('wait').value = '';
	document.getElementById('viewbox').value = '';
	document.getElementById('parallel').checked = false;
	actionChanged();
};

function resetLink()
{
	document.getElementById('link').value = 'data:action/json,' + JSON.stringify({"actions":[]}, null, 2);
};

function validateLink(quiet)
{
	try
	{
		var href = document.getElementById('link').value;
		var start = href.indexOf('data:action/json,');
		var link = JSON.parse(href.substring(start + 17));

		if (link.actions == null || link.actions.length == 0)
		{
			throw 'No actions';
		}
		else if (!quiet)
		{
			document.getElementById('link').value = 'data:action/json,' + JSON.stringify(link, null, 2);
			showMessage('Link is valid');
		}

		return true;
	}
	catch (e)
	{
		var index = (e.message != null) ? e.message.indexOf(' at position ') : 0;

		if (index > 0)
		{
			var pos = parseInt(e.message.substring(index + 13));
			setCaretPosition('link', pos + 14);
		}
		
		showMessage('Error: ' + e);
	}
};

function showMessage(message)
{
	var confirmation = document.getElementById('confirmation');
	confirmation.style.display = '';
	confirmation.innerHTML = message;

	window.setTimeout(function()
	{
		confirmation.style.display = 'none';
	}, 3000);
};

function setCaretPosition(elemId, caretPos)
{
    var elem = document.getElementById(elemId);

    if (elem != null)
	{
		elem.focus();

        if (elem.createTextRange)
		{
            var range = elem.createTextRange();
            range.move('character', caretPos);
            range.select();
        }
        else if (elem.selectionStart)
		{
			elem.setSelectionRange(caretPos, caretPos);
		}
    }
};

function copyLink()
{
	try
	{
		if (validateLink(true))
		{
			var link = document.getElementById('link');
			var prev = link.value;
			link.value = 'data:action/json,' + JSON.stringify(JSON.parse(link.value.substring(17)));
			link.focus();
			link.select();
			document.execCommand('copy');
			link.value = prev;
			showMessage('Link Copied');
		}
	}
	catch (e)
	{
		showMessage('Error: ' + e);
	}
};

function actionChanged()
{
	var action = document.getElementById('action').value;
	document.getElementById('keyBox').style.display =
		(action == 'style' || action == 'toggleStyle') ? '' : 'none';
	document.getElementById('valueBox').style.display =
		(action == 'style' || action == 'opacity') ? '' : 'none';
};

</script>
</head>
<body style="font-family:sans-serif;" onload="resetLink();actionChanged();document.getElementById('cells').focus();">
	<span style="position:relative;display:inline-block;left:50%;transform:translate(-50%,0);">
		<h2 style="text-align:center;width:100%;">Create Custom Link</h2>
		<hr>
		1. Action for Cell(s): <select id="action" onchange="actionChanged();">
			<option value="toggle" selected>Toggle</option>
			<option value="show">Show</option>
			<option value="hide">Hide</option>
			<option value="style">Set Style</option>
			<option value="toggleStyle">Toggle Style</option>
			<option disabled>-</option>
			<option value="opacity">Opacity</option>
			<option value="wipeIn">Wipe In</option>
			<option value="wipeOut">Wipe Out</option>
			<option value="fadeIn">Fade In</option>
			<option value="fadeOut">Fade Out</option>
			<option value="highlight">Highlight</option>
			<option value="select">Select</option>
			<option value="scroll">Scroll</option>
		</select>
		<span id="keyBox">Key: <input type="text" size="20" id="key" placeholder="flowAnimation"></input></span>
		<span id="valueBox">Value: <input type="text" size="20" id="value" placeholder="1"></input></span>
		<br><br>
		2. Cells/Layers: <input type="text" size="60" id="cells" placeholder="1 2 3"></input> Space-separated list of cell or layer IDs, * for all
		<br><br>
		3. Tags: <input type="text" size="60" id="tags" placeholder="water pipes"></input> Space-separated list of tags, * for all
		<br><br>
		4. Exclude Cells/Layers: <input type="text" size="60" id="exclude" placeholder="1 2 3"></input> Space-separated list of cell or layer IDs
		<br><br>
		5. <button onclick="add();return false;" style="font-weight:bold;">Add Action</button>
		<input type="checkbox" id="parallel"> Run at the same time
		<br><hr>
		Or <button onclick="add('link');return false;" style="font-weight:bold;">Add Link:</button>
		&nbsp;<input type="text" size="60" id="href" placeholder="data:page/id,d77c2f53-a0fe-16b8-c644-547af6ee0c87"></input>
		Custom link or hyperlink
		<br><hr>
		Or <button onclick="add('wait');return false;" style="font-weight:bold;">Add Wait:</button>
		&nbsp;<input type="text" size="5" id="wait" placeholder="1000"></input>
		milliseconds
		<br><hr>
		Or <button onclick="add('viewbox');return false;" style="font-weight:bold;">Add Viewbox:</button>
		&nbsp;<input type="text" size="60" id="viewbox"></input>
		x y width height border
		<br><hr>
		Or <button onclick="add('tags');return false;" style="font-weight:bold;">Add Tags:</button>
		&nbsp;Hidden: <input type="text" size="24" id="hiddenTags"></input>
		&nbsp;Visible: <input type="text" size="24" id="visibleTags"></input> Space-separated list of tags, * for all
		<br><hr>
		<button onclick="clearInput();return false;">Clear Input</button>
		<br><hr>
		Custom Link:
		<br>
		<textarea rows="12" cols="100" id="link" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off"></textarea>
		<br>
		<button onclick="window.open('https://www.diagrams.net/doc/faq/custom-links');">Help</button>
		<button onclick="validateLink();return false;">Validate</button>
		<button onclick="resetLink();return false;">Reset Link</button>
		<button onclick="copyLink();return false;"><b>Copy Link</b></button>
		<span id="confirmation" style="display:none;font-size:10pt;padding:3px;font-weight:bold;"></span>
	</span>
</body>
</html>
